package com.chucang.shucang.pms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chucang.shucang.common.base.constant.SecurityConstant;
import com.chucang.shucang.common.base.exception.FastException;
import com.chucang.shucang.common.base.page.PageData;
import com.chucang.shucang.common.base.page.PageQuery;
import com.chucang.shucang.common.base.redis.RedisUtil;
import com.chucang.shucang.common.base.service.impl.CrudServiceImpl;
import com.chucang.shucang.common.base.utils.CaffeineUtil;
import com.chucang.shucang.common.base.utils.DecToSfUtil;
import com.chucang.shucang.common.base.utils.OpsUtil;
import com.chucang.shucang.common.base.utils.R;
import com.chucang.shucang.pms.constant.PmsCacheConstant;
import com.chucang.shucang.pms.constant.PmsCommonConstant;
import com.chucang.shucang.pms.dao.CollectionSyntheticDao;
import com.chucang.shucang.pms.dto.CollectionSyntheticDTO;
import com.chucang.shucang.pms.entity.CollectionBaseEntity;
import com.chucang.shucang.pms.entity.CollectionSyntheticEntity;
import com.chucang.shucang.pms.feign.UserService;
import com.chucang.shucang.pms.feign.vo.UserBaseEntity;
import com.chucang.shucang.pms.service.CollectionBaseService;
import com.chucang.shucang.pms.service.CollectionSyntheticService;
import com.chucang.shucang.pms.vo.CollectionSyntheticPageResVO;
import com.chucang.shucang.pms.vo.SyntheticCollectionDetailResVO;
import com.chucang.shucang.pms.vo.query.CollectionSyntheticQuery;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * 藏品合成表
 *
 * @author flitsneak flitsneak@gmail.com
 * @since 1.0.0 2022-09-12
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CollectionSyntheticServiceImpl extends CrudServiceImpl<CollectionSyntheticDao, CollectionSyntheticEntity, CollectionSyntheticDTO> implements CollectionSyntheticService {
    private final CollectionBaseService collectionBaseService;
    private final UserService userService;
    private final RedissonClient redissonClient;
    private final RedisUtil redisUtil;
    private final CaffeineUtil caffeineUtil;

    private static final int SYNTHETIC_OVER = 2;
    private static final int ON_SYNTHETIC = 1;
    private static final int PRE_SYNTHETIC = 0;

    @Override
    public PageData<CollectionSyntheticPageResVO> collectionSyntheticPage(CollectionSyntheticQuery collectionSyntheticQuery) {
        LambdaQueryWrapper<CollectionBaseEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(CollectionBaseEntity::getStatus, PmsCommonConstant.ON_SHELF)
                .eq(CollectionBaseEntity::getDcAttribute, PmsCommonConstant.FOR_SYNTHETIC)
                .select()
                .orderByDesc(CollectionBaseEntity::getCreateTime);
        IPage<CollectionBaseEntity> page = collectionBaseService.page(
                new PageQuery<CollectionBaseEntity>().getPage(collectionSyntheticQuery),
                lambdaQueryWrapper
        );
        if (CollUtil.isEmpty(page.getRecords())) {
            return new PageData<>(Collections.emptyList(), 0);
        }
        //收集发行人信息
        Map<Long, String> stringHashMap = new HashMap<>(32);
        Set<Long> set = new HashSet<>(16);
        page.getRecords().forEach(c ->
                set.add(c.getPublisherId())
        );
        //发行人
        R<List<UserBaseEntity>> baseInfo = userService.listUserBaseInfo(set, SecurityConstant.FROM_IN);
        List<UserBaseEntity> baseEntities = OpsUtil.of(baseInfo)
                .assertDataNotNull(e -> new FastException("查询用户信息异常"))
                .getData()
                .get();
        baseEntities.forEach(d ->
                stringHashMap.put(d.getId(), d.getUsername())
        );
        List<CollectionSyntheticPageResVO> basePageResVOS = BeanUtil.copyToList(page.getRecords(), CollectionSyntheticPageResVO.class);
        basePageResVOS.forEach(b -> {
            b.setUsername(stringHashMap.get(b.getPublisherId()));
            long begin = b.getStartTime().getTime();
            long end = b.getEndTime().getTime();
            long now = new Date().getTime();
            if (begin < now && now < end) {
                if (b.getSurplus() <= 0) {
                    b.setStatus(SYNTHETIC_OVER);
                } else {
                    b.setStatus(ON_SYNTHETIC);
                    //正在合成
                    String uuid = DecToSfUtil.toNameSf(b.getId());
                    if (Objects.isNull(caffeineUtil.getObject(b.getId().toString()))) {
                        if (!redisUtil.hasKey(String.format(PmsCacheConstant.COLLECTION_SYNTHETIC_STOCK, b.getId()))) {
                            redisUtil.setValue(String.format(PmsCacheConstant.COLLECTION_SYNTHETIC_STOCK, b.getId()), 0, end - now, TimeUnit.MILLISECONDS);
                            //放入信号量
                            RSemaphore semaphore = redissonClient.getSemaphore(String.format(PmsCacheConstant.COLLECTION_SYNTHETIC, uuid));
                            semaphore.trySetPermits(b.getTotalNum());

                            caffeineUtil.setValue(b.getId().toString(), uuid);
                        }
                    }
                }
            } else if (now < begin) {
                b.setStatus(PRE_SYNTHETIC);
            } else if (now > end) {
                b.setStatus(SYNTHETIC_OVER);
            }
        });
        return new PageData<>(basePageResVOS, page.getTotal());
    }

    @Override
    public SyntheticCollectionDetailResVO getSyntheticCollectionDetail(Long id) {
        //在售信息
        CollectionBaseEntity byId = collectionBaseService.getById(id);

        SyntheticCollectionDetailResVO syntheticCollectionDetailResVO = new SyntheticCollectionDetailResVO();
        BeanUtil.copyProperties(byId, syntheticCollectionDetailResVO);
        long begin = byId.getStartTime().getTime();
        long end = byId.getEndTime().getTime();
        long now = new Date().getTime();
        if (begin < now && now < end) {
            if (byId.getSurplus() <= 0) {
                syntheticCollectionDetailResVO.setStatus(SYNTHETIC_OVER);
            } else {
                syntheticCollectionDetailResVO.setStatus(ON_SYNTHETIC);
                String uuid = DecToSfUtil.toNameSf(byId.getId());
                syntheticCollectionDetailResVO.setSyntheticKey(uuid);
            }
        } else if (now < begin) {
            syntheticCollectionDetailResVO.setStatus(PRE_SYNTHETIC);
        } else if (now > end) {
            syntheticCollectionDetailResVO.setStatus(SYNTHETIC_OVER);
        }
        //账号信息
        R<UserBaseEntity> baseInfoById = userService.getUserBaseInfoById(byId.getPublisherId(), SecurityConstant.FROM_IN);
        UserBaseEntity userBaseEntity = OpsUtil
                .of(baseInfoById)
                .assertDataNotNull(e -> new FastException("获取用户信息失败"))
                .getData()
                .get();

        syntheticCollectionDetailResVO.setUsername(userBaseEntity.getUsername());
        syntheticCollectionDetailResVO.setOffshoreAccount(userBaseEntity.getOffshoreAccount());
        syntheticCollectionDetailResVO.setAccountType(userBaseEntity.getAccountType());

        return syntheticCollectionDetailResVO;
    }
}